#include "engine.hpp"

#define LOGE(...) zj_logger_e("engine_main", __VA_ARGS__)
#if defined(ZJ_DEBUG_ALL) || defined(ZJ_DEBUG_MAIN)
#  define LOGD(...) zj_logger_d("engine_main", __VA_ARGS__)
#else
#  define LOGD(...) (void)0
#endif

Engine::Engine(struct android_app* app)
        : data_path('/'), can_draw(false), need_draw(false), pen(0)
{
    this->app = app;
    init();
}

Engine::~Engine()
{
    destroy();
}

static void handle_cmd_proxy(struct android_app* app, int32_t cmd)
{ ((Engine*)app->userData)->handle_cmd(app, cmd); }
static int32_t handle_input_proxy(struct android_app* app, AInputEvent* event)
{ return ((Engine*)app->userData)->handle_input(app, event); }

void Engine::init()
{
    data_path = zj_string(app->activity->externalDataPath) + '/';
    zj_logger_init(data_path.c_str(), 0);
    zj_logger_open_debug();
    LOGD("%s", zj_logger_get_file_path());

    app->onAppCmd     = handle_cmd_proxy;
    app->onInputEvent = handle_input_proxy;
    app->userData     = this;

    pen = new zj_pen();
}

void Engine::destroy()
{
    can_draw  = false;
    need_draw = false;
    delete pen;
}

void Engine::handle_cmd(struct android_app* app, int32_t cmd)
{
    switch (cmd) {
        case APP_CMD_INIT_WINDOW:
            zjglue_init_display(app, &egl);
            pen->init();
            need_draw = true;
            break;
        case APP_CMD_TERM_WINDOW:
            pen->destroy();
            zjglue_term_display(&egl);
            break;
    }
}

int exit_button_size = 200;
bool exit_button_down = false;

int32_t Engine::handle_input(struct android_app* app, AInputEvent *event)
{
    switch (AInputEvent_getType(event)) {
        case AINPUT_EVENT_TYPE_MOTION:
            hx = AMotionEvent_getX(event, 0);
            hy = AMotionEvent_getY(event, 0);
            exit_button_down = false;
            switch (AMotionEvent_getAction(event)) {
                case AMOTION_EVENT_ACTION_DOWN:
                    /*if (mx <= exit_button_size && my <= exit_button_size) {
                        exit_button_down = true;
                    }*/
                    break;
                case AMOTION_EVENT_ACTION_MOVE:
                    /*if (mx <= exit_button_size && my <= exit_button_size) {
                        exit_button_down = true;
                    }*/
                    break;
                case AMOTION_EVENT_ACTION_UP:
                    if (hx <= exit_button_size && hy <= exit_button_size) {
                        ANativeActivity_finish(app->activity);
                    }
                    break;
                default:
                    break;
            }

        case AINPUT_EVENT_TYPE_KEY:
            LOGD("Key code: %d", AKeyEvent_getKeyCode(event));
            break;
    }
    return 0;
}

void Engine::loop()
{
    while (true) {
        int ident, events;
        struct android_poll_source* source;
        while ((ident=ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
            if (source) source->process(app, source);
            if (app->destroyRequested) return;
        }

        if (pen->is_inited()) {
            can_draw = true;
            need_draw = true;
        } else {
            can_draw = false;
        }

        if (can_draw && need_draw)
        {
            zjglue_get_wh(egl, &w, &h);
            pen->set_scrwh(w, h);
            draw();
            glViewport(0, 0, w, h);
            eglSwapBuffers(egl.display, egl.surface);
            need_draw = false;
        }
    }
}

zj_color color_exit_button_down(0.5, 0.5, 0.5, 1);
zj_color color_exit_button(1, 1, 1, 1);

void Engine::draw()
{
    pen->clear(zj_color((float)hx/w, 0, 0, 1));

    pen->set_color(color_exit_button);
    pen->fill_rect(zj_rect(0, 0, exit_button_size, exit_button_size));

    pen->fill_circle(zj_point(hx, hy), 130);
}